#include "arvsint.h"

No *novoNo(){
	No *novo;
	novo = malloc(sizeof(No));
	novo->op1 = NULL;
	novo->op2 = NULL;
	novo->op3 = NULL;
	novo->op4 = NULL;
	novo->proximo = NULL;
	novo->nome = NULL;
	return novo;
}

void ajustaOp1(No *no, No *op){
	no->op1 = op;
}

void ajustaOp2(No *no, No *op){
	no->op2 = op;
}

void ajustaOp3(No *no, No *op){
	no->op3 = op;
}

void ajustaOp4(No *no, No *op){
	no->op4 = op;
}

void ajustaProximo(No *no, No *proximo){
	no->proximo = proximo;
}

void ajustaNome(No *no, char *nome){
	no->nome = nome;
}

No *novoNoGoal(char * nome){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_GOAL;
	novo->nome = nome;
	return novo;
}

No *novoNoMainClasse(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_MNCS;
	return novo;
}

No *novoNoDeclaracaoDeClasse(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_DECS;
	return novo;
}

No *novoNoDeclaracaoDeMetodo(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_METD;
	return novo;
}

No *novoNoExtende(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_EXTD;
	return novo;
}

No *novoNoExpressao(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_EXP;
	return novo;
}


No *novoNoMais(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_PLUS;
	return novo;
}

No *novoNoMenos(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_SUBT;
	return novo;
}

No *novoNoMultiplicacao(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_MULT;
	return novo;
}

No *novoNoDivisao(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_DIVD;
	return novo;
}

No *novoNoAtribuicao(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_ASSG;
	return novo;
}

No *novoNoChamada(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_CALL;
	return novo;
}

No *novoNoSe(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_IF;
	return novo;
}

No *novoNoEnquanto(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_WHLE;
	return novo;
}

No *novoNoE(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_AND;
	return novo;
}

No *novoNoOu(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_OR;
	return novo;
}

No *novoNoNegacao(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_NOT;
	return novo;
}

No *novoNoIgual(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_EQ;
	return novo;
}

No *novoNoTipo(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_TIPO;
	return novo;
}

No *novoNoDiferente(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_NEQ;
	return novo;
}

No *novoNoMenor(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_LT;
	return novo;
}

No *novoNoMenorOuIgual(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_LE;
	return novo;
}

No *novoNoMaior(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_GT;
	return novo;
}

No *novoNoMaiorOuIgual(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_GE;
	return novo;
}

No *novoNoDeclaracaoDeVar(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_VARD;
	return novo;
}

No *novoNoImprimir(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_PRINT;
	return novo;
}

No *novoNoInteiro(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_INT;
	return novo;
}

No *novoNoId(){
	No *novo;
	novo = novoNo();
	novo->rotulo = T_ID;
	return novo;
}

void identa(int nivel){
	int i;
	for(i = 0; i < nivel; i++) printf(" ");
}

void mostraArvore(No *arvore, int nivel){
	if(arvore == NULL) return;
	switch(arvore->rotulo){
		case T_GOAL:
			printf("Programa\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_MNCS:
			identa(nivel);
			printf("Classe Principal: %s String[] %s\n", arvore->op1->nome,arvore->op2->nome);
			mostraArvore(arvore->op3, nivel);
			break;
		case T_DECS:
			identa(nivel);
                        if (arvore->op2 == NULL)
			  printf("Classe: %s \n", arvore->op1->nome);
			else
                          printf("Classe: %s extende de %s\n", arvore->op1->nome,arvore->op2->op1->nome);                         
				
			mostraArvore(arvore->op3, nivel+1);
			mostraArvore(arvore->op4, nivel+1);			
			break;
		case T_PLUS:
			identa(nivel);
			printf("Soma\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_EXTD:
			identa(nivel);
			printf("Extende\n");
			mostraArvore(arvore->op1, nivel+1);
			break;
		case T_TIPO:
			identa(nivel);
			printf("Tipo %s \n",arvore->nome);
			break;
		case T_SUBT:
			identa(nivel);
			printf("Subtracao\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_EXP:
			identa(nivel);
			printf("Expressao\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_MULT:
			identa(nivel);
			printf("Multiplicacao\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_DIVD:
			identa(nivel);
			printf("Divisao\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_ASSG:
			identa(nivel);
			printf("Atribuicao\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			mostraArvore(arvore->proximo, nivel);
			break;
		case T_CALL:
			identa(nivel);
			printf("Comando:");
			mostraArvore(arvore->op1, nivel);
			mostraArvore(arvore->proximo, nivel);
			break;
		case T_IF:
			identa(nivel);
			printf("Se\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_WHLE:
			identa(nivel);
			printf("Enquanto\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			mostraArvore(arvore->proximo, nivel);
			break;
		case T_AND:
			identa(nivel);
			printf("E\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_OR:
			identa(nivel);
			printf("Ou\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_NOT:
			identa(nivel);
			printf("Negacao\n");
			mostraArvore(arvore->proximo, nivel);
			break;
		case T_EQ:
			identa(nivel);
			printf("Igual\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_NEQ:
			identa(nivel);
			printf("Diferente\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_LT:
			identa(nivel);
			printf("Menor que\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_LE:
			identa(nivel);
			printf("Menor ou igual\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_GT:
			identa(nivel);
			printf("Maior que\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_GE:
			identa(nivel);
			printf("Maior ou igual\n");
			mostraArvore(arvore->op1, nivel+1);
			mostraArvore(arvore->op2, nivel+1);
			break;
		case T_VARD:
			identa(nivel);
			printf("Declaracao\n");
			mostraArvore(arvore->proximo, nivel);
			break;
		case T_PRINT:
			identa(nivel);
			printf("Imprime\n");
			mostraArvore(arvore->op1, nivel+1);
			break;
                case T_METD:
			identa(nivel);
			printf("Metodo\n");
			mostraArvore(arvore->proximo, nivel);
			break;
		case T_INT:
			identa(nivel);
			printf("Inteiro: %s\n", arvore->nome);
			mostraArvore(arvore->proximo, nivel);
			break;
		case T_ID:
			identa(nivel);
			printf("Identificador: %s\n", arvore->nome);
			mostraArvore(arvore->proximo, nivel);
			break;
		default:
			printf("Algo muito estranho aconteceu!\n");
			break;
	}
}

void destroiArvore(No *arvore){
	if(arvore == NULL) return;
	if(arvore->nome != NULL)
		free(arvore->nome);
	destroiArvore(arvore->op1);
	destroiArvore(arvore->op2);
	destroiArvore(arvore->op3);
	destroiArvore(arvore->proximo);
	free(arvore);
}
